/*
 * PbbWikiCom.java
 *
 * Created on July 11, 2007, 2:59 PM
 *
 *Copyright 2007-2008 Jon W Huss III

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 *
 */
package pbb_template_updater;

import java.net.*;
import java.io.*;
import java.net.CookieManager;
import java.util.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import ApacheLang.StringEscapeUtils;
//Test imports


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

/**
 *
 * @author Jon Huss
 */
public class PbbWikiCom {
    //read wait is only used when the server is lagged.
    public static final int READ_WAIT = 5000;
    public static final int READ_MAX_WAIT = 100000;
    public static final int WRITE_WAIT = 6000;
    public static final int LOGIN_WAIT = 4000;
    public static final int MAX_LAG = 5; //As suggested at http://www.mediawiki.org/wiki/Manual:Maxlag_parameter
    //Extra info for uploading imageFiles to Wikipedia
    public static final String pdbImageCopyright = "www.pdb.org {{PD-release}}";
    public static final String WIKI_FILE_UPLOAD = "http://en.wikipedia.org/wiki/Special:Upload";
    public static final String WIKI_NO_IMAGE = "No file by this name exists;";
    public static final String WIKI_NO_IMAGE2 = "Wikipedia does not have an Image page with this exact title.";
    private URL baseURL;
    private CookieStore cStore;
    private String userName;
    private String password;
    //private PBBLogging log;
    private Date nextComm;
    private Random myRand;
    private Vector<String> infoLog; //Going to track wiki activity via a simple log, instead of the more complicated one.

    /** Creates a new instance of PbbWikiCom */
    public PbbWikiCom(String uName, String pWord, String wUrl) throws Exception {
        infoLog = new Vector<String>();

        myRand = new Random();
        nextComm = new Date();
        //log = l;
        userName = uName;
        password = pWord;
        try {
            baseURL = new URL(wUrl);
        } catch (Exception e) {

            System.out.println("Problem with the URL:" + wUrl);

            throw e;
        }
        java.net.CookieManager cm = new java.net.CookieManager();
        cm.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        java.net.CookieHandler.setDefault(cm);
        cStore = cm.getCookieStore();

    }

    public static final String geneExpImageCopyrightFull(String name) {

        String tmp = "==Summary==\r\n" +
                "{{PBB Image citation|gene=" + name + "}}\r\n" +
                "\r\n== Licensing == \r\n" +
                "{{GFDL-no-disclaimers}}\r\n{{cc-by-sa-3.0|[[Genomics Institute of the Novartis Research Foundation]]}}";


        return tmp;
    }

    public static final String geneExpImageCopyrightThumb(String geneName, String fullSizeName) {

        String tmp = "==Summary==\r\n" +
                "{{PBB Image citation|gene=" + geneName + "|fullsize=Image:" + fullSizeName + "}}\r\n" +
                "\r\n== Licensing == \r\n" +
                "{{GFDL-no-disclaimers}}\r\n{{cc-by-sa-3.0|[[Genomics Institute of the Novartis Research Foundation]]}}";


        return tmp;
    }

    public static final String pdbImage(String pdb) {
        return "http://www.rcsb.org/pdb/images/" + pdb + "_bio_r_500.jpg?bioNum=1";
    }

    public void uploadImage(String page, byte[] imageData, String imageCopyright) throws Exception {
        //wraps for error catching.
        boolean clear = false;
        int tries = 0;
        infoLog.add("Starting upload of image to " + page);
        while (!clear) {

            try {
                if (PbbUpdater.debugUpload == true) {
                    uploadImageH(page, imageData, imageCopyright);
                } else {
                    infoLog.add("Upload skipped due to Debug Upload being false.");
                    System.out.println("Upload skipped due to Debug Upload being false.");
                }
                infoLog.add("Upload successful.");
                return;
            } catch (Exception e) {
                System.out.println("Encountered Error while Uploading Image:");
                infoLog.add("Encountered Error while Uploading Image:  " + e.getMessage());
                System.out.println(e.getMessage());
                if (tries < 3) {
                    System.out.println("Trying " + (3 - tries) + " more time(s) in 10 seconds...");
                    this.updateWait(10000);
                    this.allowComm();
                    tries++;


                } else {
                    System.out.println("3 tries failed; Requiring User Input:");
                    tries = 0;


                    try {
                        BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                        System.out.println("Try Again? (y/n)");
                        System.out.flush();
                        String input = inputLine.readLine();
                        //input = "y";
                        if (input.compareToIgnoreCase("y") == 0) {
                            clear = false;
                        } else {
                            clear = true;
                            infoLog.add("User Aborted Image Upload due to Error.");
                            throw new Exception("User Aborted Image Upload due to error.", e);

                        }

                    } catch (IOException ex) {
                        throw new Exception("Unrecoverable IO Error.", ex);
                    //System.out.println("Unrecoverable IO Error.");
                    //ex.printStackTrace();
                    //System.exit(1);
                    }
                }
            }
        }
        throw new Exception("Unknown Download Error.");
    //return null;
    }

    public void uploadImageH(String imageName, byte[] imageData, String imageCopyright) throws Exception {
        //Upload a jpeg image to wikipedia.
        //URL editURL;
        //URLConnection editConn;
        URL postURL;
        HttpURLConnection postConn;
        String lineSep = System.getProperty("line.separator");
        String webLineSep = "\r\n";
        this.allowComm();

        //First do a little encoding...
        imageName = encode(imageName);
        //page = encode(page);
        //editComment = encode(editComment);
        //Make sure the cookies are up to date
        //String cookieInfo = this.getCookieData();

        //DEBUG
        //System.out.println(cookieInfo);

        postURL = new URL(this.WIKI_FILE_UPLOAD);
        //postURL = new URL("http://192.168.1.101/");
        postConn = (HttpURLConnection) postURL.openConnection();
        postConn.setRequestMethod("POST");
        //System.out.println(postConn.getRequestProperty("Cookie"));
        setCookies(postConn);
        //postConn.setRequestProperty("Cookie", cookieInfo);
        //System.out.println(postConn.getRequestProperty("Cookie"));

        //long bNum = myRand.nextLong();
        String bNum = "";
        for (int i = 0; i < 12; i++) {
            bNum = bNum + myRand.nextInt(10);
        }

        String fieldBreak = "---------------------------" + bNum;
        //Now we need to build up all the info we are sending...
        String conDisp = "Content-Disposition: form-data; ";
        String sendData = "";
        sendData = sendData + "--" + fieldBreak + webLineSep;
        sendData = sendData + conDisp + "name=\"wpSourceType\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "file" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpDestFile\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + imageName + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpUploadDescription\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + imageCopyright + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpLicense\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpWatchthis\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "true" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpUpload\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "Upload file" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpDestFileWarningAck\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "1" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpIgnoreWarning\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "0" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        //Now send the actual file data...
        sendData = sendData + conDisp + "name=\"wpUploadFile\"; filename=\"" + imageName + "\"" + webLineSep;
        sendData = sendData + "Content-Type: image/jpeg" + webLineSep;
        //sendData = sendData + "Content-Transfer-Encoding: binary" + webLineSep;

        sendData = sendData + webLineSep;

        String dataEnd = webLineSep + "--" + fieldBreak + "--" + webLineSep;
        postConn.setDoOutput(true);
        postConn.setDoInput(true);
        postConn.setUseCaches(false);
        postConn.setRequestProperty("Content-Length", String.valueOf((sendData.length() + dataEnd.length() + imageData.length)));
        postConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + fieldBreak);

        //BEGIN DEBUG
        //System.out.println("Request Properties: " + postConn.getRequestProperties().toString());
        //END DEBUG
        //log.addEntry("SYSTEM","HTTP:WIKICOMM","Uploading Image to:"+ postURL.toString(),PBBLogging.logs.SY);

        //debug stuff here
        //PipedOutputStream sniffOut;
        //PipedInputStream sniffIn;

        //System.out.println("Uploading Image...");
        OutputStream out = postConn.getOutputStream();
        //ByteArrayOutputStream bOut = new ByteArrayOutputStream(out);

        PrintWriter outp = new PrintWriter(out);

        //sniffIn = new PipedInputStream(out);
        //System.setErr(new PrintStream(out));
        outp.print(sendData);
        outp.flush();
        //write out the actual image data...
        out.write(imageData);
        out.flush();

        outp.print(dataEnd);
        outp.flush();
        outp.close();
        //end the communication
        //System.setErr(System.err);

        //Form Fields:
        //wpSourceType = file
        //wpUploadFile
        //wpDestFile
        //wpUploadDescription
        //

        //log.addEntry("SYSTEM","WIKICOMM","Finished Uploading Image:" + imageName,PBBLogging.logs.SY);

        //System.out.println("Finished Uploading Image.");

        BufferedReader br = new BufferedReader(new InputStreamReader(postConn.getInputStream()));
        String info = "";
        //check out the response for any errors
        while (br.ready()) {
            info = info + br.readLine() + lineSep;
        }

        postConn.getContent();

        //DEBUG
        //System.err.print(info);
        //--DEBUG

        this.updateWait(this.WRITE_WAIT);
        //Looks good.
        return;

    //} catch (Exception e){
    //    System.out.println("Error while Uploading to: " + page);
    //    return;
    //}


    }

    public boolean wikiHasImage(String page) throws Exception {
        //wraps for error catching.
        boolean clear = false;
        int tries = 0;
        infoLog.add("Checking existance of image, " + page + " on wiki...");
        while (!clear) {

            try {
                boolean data = wikiHasImageH(page);
                infoLog.add("Done. Image Existance is: " + data);
                return data;
            } catch (Exception e) {
                System.out.println("Encountered Error while Downloading:");
                System.out.println(e.getMessage());
                if (tries < 3) {
                    System.out.println("Trying " + (3 - tries) + " more time(s) in 10 seconds...");
                    this.updateWait(10000);
                    this.allowComm();
                    tries++;


                } else {
                    System.out.println("3 tries failed; Requiring User Input:");
                    tries = 0;

                    try {
                        BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                        System.out.println("Try Again? (y/n)");
                        System.out.flush();
                        String input = inputLine.readLine();
                        //input = "y";
                        if (input.compareToIgnoreCase("y") == 0) {
                            clear = false;
                        } else {
                            clear = true;
                            throw new Exception("User Aborted Download due to error.", e);

                        }

                    } catch (IOException ex) {
                        throw new Exception("Unrecoverable IO Error.", ex);
                    //System.out.println("Unrecoverable IO Error.");
                    //ex.printStackTrace();
                    //System.exit(1);
                    }
                }
            }
        }
        throw new Exception("Unknown Download Error.");
    //return null;
    }

    public boolean wikiHasImageH(String page) throws Exception {
        //Returns the data of the indicated page. It is found in the wpTextbox1 area.
        String lineSep = System.getProperty("line.separator");
        page = encode(page);
        URL editURL;
        //URLConnection editConn;
        //String data = "";
        HttpURLConnection editConn;
        //String data = "";
        String fullData = "";

        //So max lag check is to speed up reading of the wiki pages, unless they are bogged down.
        //we will get a response of a single line if the server lags - we then need to wait for some amount
        //of time and repoll the server.
        editURL = new URL(baseURL, "index.php?title=" + page + "&action=edit&maxlag=" + this.MAX_LAG);
        //log.addEntry("SYSTEM","WIKICOMM","Checking Image Page:"+ editURL.toString(),PBBLogging.logs.SY);

        MAX_LAG_CHECK:
        {
            boolean maxLagError = true;
            while (maxLagError) { //so go at least once.

                this.allowComm();

                editConn = (HttpURLConnection) editURL.openConnection();
                setCookies(editConn);
                //editConn.setRequestProperty("Cookie", this.getCookieData());
                try {

                    editConn.getContent();
                } catch (IOException ex) {

                    if (editConn.getResponseCode() == HttpURLConnection.HTTP_UNAVAILABLE) {
                        BufferedReader br;

                        br = new BufferedReader(new InputStreamReader(editConn.getErrorStream()));

                        String line;

                        int readCount = 0;
                        fullData = "";
                        while ((line = br.readLine()) != null) {
                            fullData = fullData + line + lineSep;
                            readCount++;
                        }
                        if (readCount < 3) { //only read one or two lines - something was wrong.
                            if (fullData.matches("Waiting for .*: .* seconds lagged\\s*")) {
                                //looks like we were lagged
                                System.out.println("Server Lagged on Read. " + fullData);
                                String[] words = fullData.split("\\s+");
                                int waitTime = 0;
                                if (words.length > 3) {
                                    try {
                                        waitTime = Integer.parseInt(words[3]) * 1000;
                                    } catch (NumberFormatException nfe) {
                                        waitTime = 0;
                                    }
                                }

                                if (waitTime < this.READ_WAIT) {
                                    waitTime = this.READ_WAIT;
                                }

                                this.updateWait(waitTime);
                                //this.updateWait(this.READ_WAIT);
                                continue;
                            } else {
                                throw ex;
                            }
                        } else {
                            throw ex;
                        }
                    } else {
                        throw ex;
                    }
                }

                //If we get here, then no lag occured. 
                BufferedReader br = new BufferedReader(new InputStreamReader(editConn.getInputStream()));
                String line;
                fullData = "";

                while ((line = br.readLine()) != null) {
                    fullData = fullData + line + lineSep;
                }

                //We got the data, lets get out of this loop.
                maxLagError = false;
            //deviation from the normal download here - we need to look and see if this page is existing.

            }

        } //END MAX_LAG_CHECK

        //We just need to see if Wikipedia reports an error or not. 
        if (fullData.indexOf(WIKI_NO_IMAGE) != -1) {
            return false;
        } else if (fullData.indexOf(WIKI_NO_IMAGE2) != -1) {
            return false;
        }
        return true;

    }

    public byte[] downloadPdbImage(String pdb) throws Exception {
        //wraps for error catching.
        boolean clear = false;
        int tries = 0;
        while (!clear) {

            try {
                byte[] data = downloadPdbImageH(pdbImage(pdb));
                return data;
            } catch (Exception e) {
                System.out.println("PDB: Encountered Error while Downloading:");
                System.out.println(e.getMessage());
                if (tries < 3) {
                    System.out.println("Trying " + (3 - tries) + " more time(s) in 10 seconds...");
                    this.updateWait(10000);
                    this.allowComm();
                    tries++;

                } else {
                    System.out.println("3 tries failed; Requiring User Input:");
                    tries = 0;

                    try {
                        BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                        System.out.println("Try Again? (y/n)");
                        System.out.flush();
                        String input = inputLine.readLine();
                        //input = "y";
                        if (input.compareToIgnoreCase("y") == 0) {
                            clear = false;
                        } else {
                            clear = true;
                            throw new Exception("User Aborted Download due to error.", e);

                        }

                    } catch (IOException ex) {
                        throw new Exception("Unrecoverable IO Error.", ex);
                    //System.out.println("Unrecoverable IO Error.");
                    //ex.printStackTrace();
                    //System.exit(1);
                    }
                }
            }
        }
        //bad news if we get to this location.
        throw new Exception("Unknown Download Error.");
    //return null;
    }
    //Helper method for downloadPdbImage
    private byte[] downloadPdbImageH(String page) throws Exception {
        //Returns the data of the indicated page. It is found in the wpTextbox1 area.
        String lineSep = System.getProperty("line.separator");
        //page = encode(page);
        URL pdbURL;
        URLConnection pdbConn;

        //this.allowComm();
        pdbURL = new URL(page);
        //log.addEntry("SYSTEM","PDBCOMM","Downloading File:"+ pdbURL.toString(),PBBLogging.logs.SY);

        pdbConn = pdbURL.openConnection();
        byte[] input = new byte[1024];
        InputStream pdbIs = pdbConn.getInputStream();

        int numRead;
        byte[] fullData = new byte[0];
        byte[] tmp = null;
        while ((numRead = pdbIs.read(input)) != -1) {
            tmp = fullData;
            fullData = new byte[tmp.length + numRead];
            System.arraycopy(tmp, 0, fullData, 0, tmp.length);
            System.arraycopy(input, 0, fullData, tmp.length, numRead);
        }

        //this.updateWait(this.READ_WAIT);
        return fullData;

    }

    private void updateWait(int wait) {
        Date now = new Date();
        nextComm = new Date(now.getTime() + wait);

    }

    private void allowComm() {
        //this function makes the bot wait until it is allowed to perform the next communication with Wiki.
        Date now = new Date();

        long wait = nextComm.getTime() - now.getTime();
        //System.out.println("Wait = " + wait);
        double waitTime = ((double) wait) / 1000;
        if (wait > 0) {
            System.out.println("Waiting " + waitTime + " seconds for server cooldown.");
            System.out.flush();
            long left = wait;
            while (left > 10) {
                System.out.print(".");
                System.out.print(" ");
                System.out.flush();
                try {
                    if (left > 1000) {
                        Thread.currentThread().sleep(1000);
                        left = left - 1000;
                    } else {
                        Thread.currentThread().sleep(left);
                        left = 0;

                    }
                } catch (InterruptedException ex) {
                    System.out.println("Interrupted While Sleeping. Non-hazardous Error (ignored).");
                //ex.printStackTrace();
                }


            }
            Date time2 = new Date();
            long actWait = time2.getTime() - now.getTime();
            System.out.println(" (" + actWait + " milliseconds.)");
        //log.addEntry("SYSTEM","SLEPT","Waited " + actWait + " milliseconds for Server Cooldown.",PBBLogging.logs.SY);

        }
        return;

    }

    /** Logs the user into wikipedia, this function is not needed to be called before upload page
     * as upload page will take care of the login by iteself
     */
//    public void wikiLogin() {
//        //Quick method to log the bot in.  Sets cookies as appropriate.
//        URL loginURL;
//        URLConnection loginConn;
//        String data;
//        this.allowComm();
//        try {
//            loginURL = new URL(baseURL,"index.php?title=Special:Userlogin&action=submitlogin&type=login");
//            
//            //Begin debug
//            //log.addEntry("SYSTEM","WIKI","Logging in to:"+ loginURL.toString(),PBBLogging.logs.SY);
//            
//            //System.out.println("Login URL: " + loginURL.toString());
//            //End Debug
//            loginConn = loginURL.openConnection();
//            
//            loginConn.setDoOutput(true);
//            
//            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(loginConn.getOutputStream()));
//            data = "";
//            data = encode("wpName") + "=" + encode(userName);
//            data += "&" + encode("wpPassword") + "=" + encode(password);
//            data += "&" + encode("wpRemember") + "=" + encode("1");
//            data += "&" + encode("wpLoginattempt") + "=" + encode("Log+in");
//            
//            bw.write(data);
//            bw.flush();
//            bw.close();
//            loginConn.getContent(); //Should grab cookies for us.
//            //log.addEntry("SYSTEM","WIKI","Login Successful.",PBBLogging.logs.SY);
//            this.updateWait(this.LOGIN_WAIT);
//            
//        } catch (Exception e){
//            System.out.println("Failed Login.");
//            e.printStackTrace();
//        }
//        
//    }
//    public void wikiLogin() {
//        //Quick method to log the bot in.  Sets cookies as appropriate.
//        URL loginURL;
//        HttpURLConnection loginConn;
//        String webLineSep = "\r\n";
//
//        String data;
//        this.allowComm();
//
//        //So now we need to download the login page first and collect up the cookies.  otherwise Wikipedia
//        //will think that we don't allow the setting of cookies.... Too bad. 
//
////        try {
////            loginURL = new URL(baseURL, "api.php");
////            loginConn = (HttpURLConnection) loginURL.openConnection();
////            grabCookies(loginConn, cookies);
////            loginConn.getContent(); //Should grab cookies for us.
////            BufferedReader br = new BufferedReader(new InputStreamReader(loginConn.getInputStream()));
////            String info = "";
////            //check out the response for any errors
////            while (br.ready()) {
////                info = info + br.readLine() + "\n";
////            }
////
////        } catch (Exception e) {
////            System.out.println("Failed Login.");
////            e.printStackTrace();
////        }
//
//
//        try {
//            loginURL = new URL(baseURL, "api.php");
//            loginConn = (HttpURLConnection) loginURL.openConnection();
//            //loginConn = loginURL.openConnection();
//
//            //loginConn.setDoOutput(true);
//            loginConn.setRequestMethod("POST");
//            setCookiesLogin(loginConn, cookies);
//
//            String bNum = "";
//            for (int i = 0; i < 12; i++) {
//                bNum = bNum + myRand.nextInt(10);
//            }
//
//            String fieldBreak = "---------------------------" + bNum;
//            //Now we need to build up all the info we are sending...
//            String conDisp = "Content-Disposition: form-data; ";
//            String sendData = "";
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//            
//            sendData = sendData + conDisp + "name=\"action\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + "login" + webLineSep;
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//            
//            sendData = sendData + conDisp + "name=\"lgname\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + userName + webLineSep;
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//
////            sendData = sendData + conDisp + "name=\"lgpassword\"" + webLineSep;
////            sendData = sendData + webLineSep;
////            sendData = sendData + password + webLineSep;
////            sendData = sendData + "--" + fieldBreak + webLineSep;
//
//            sendData = sendData + conDisp + "name=\"format\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + "xml" + webLineSep;
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//
//            //Last entry
//            sendData = sendData + conDisp + "name=\"lgpassword\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + password + webLineSep;
//            sendData = sendData + webLineSep + "--" + fieldBreak + "--" + webLineSep;
//
//            //setup the communicator for output...
//            loginConn.setDoOutput(true);
//            loginConn.setDoInput(true);
//            loginConn.setUseCaches(false);
//            loginConn.setRequestProperty("Content-Length", String.valueOf(sendData.length()));
//            loginConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + fieldBreak);
//
//            System.out.println("Posting Data...");
//
//
//            OutputStream out = loginConn.getOutputStream();
//
//            //PrintWriter outp = new PrintWriter(out);
//
//            out.write(sendData.getBytes("UTF-8"));
//            out.flush();
//            out.close();
//
//
//
//
//
////            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(loginConn.getOutputStream()));
////            data = "";
////            data = encode("wpName") + "=" + encode(userName);
////            data += "&" + encode("wpPassword") + "=" + encode(password);
////            data += "&" + encode("wpRemember") + "=" + encode("1");
////            data += "&" + encode("wpLoginattempt") + "=" + encode("Log in");
////            
////            bw.write(data);
////            bw.flush();
////            bw.close();
//            
//            BufferedReader br = new BufferedReader(new InputStreamReader(loginConn.getInputStream()));
//            loginConn.getContent(); //Should grab cookies for us.
//            String info = "";
//            //check out the response for any errors
//            while (br.ready()) {
//                info = info + br.readLine() + "\n";
//            }
//
//            grabCookies(loginConn, cookies);
//            this.updateWait(PbbWikiCom.LOGIN_WAIT);
//
//        } catch (Exception e) {
//            System.out.println("Failed Login.");
//            e.printStackTrace();
//        }
//
//    }
    @SuppressWarnings("static-access")
    public void wikiLogin() {
 
        //Ok, going to try some different code from Apache to see if we can fix this cookie problem..
        //BEGIN TEST CODE
        try {
            DefaultHttpClient httpclient = new DefaultHttpClient();

            HttpGet httpget = new HttpGet(baseURL.toString() + "index.php?title=Special:Userlogin");

            HttpResponse response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();

            System.out.println("Login form get: " + response.getStatusLine());
            if (entity != null) {
                entity.consumeContent();
            }
            List<Cookie> cookiesList = httpclient.getCookieStore().getCookies();

            HttpPost httpost = new HttpPost(baseURL.toString() + "index.php?title=Special:Userlogin&action=submitlogin&type=login");

            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("wpName", userName));
            nvps.add(new BasicNameValuePair("wpPassword", password));
            nvps.add(new BasicNameValuePair("wpRemember", "1"));
            nvps.add(new BasicNameValuePair("wpLoginattempt", "Log in"));

            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

            response = httpclient.execute(httpost);
            entity = response.getEntity();

            if (entity != null) {
                entity.consumeContent();
            }

            cookiesList = httpclient.getCookieStore().getCookies();
            grabCookies(cookiesList);
            System.out.println("Successfully logged in to Wiki.");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }


        ///END TEST CODE
        //The apache code works - fixed our problem anyway.  We are going to use it for login and use the 
        //normal URL code for the rest...  We'll have to see what else is broken...




//////////OLD CODE BEGIN           
//       //Quick method to log the bot in.  Sets cookies as appropriate.
//        URL loginURL;
//        HttpURLConnection loginConn;
//        String webLineSep = "\r\n";
//
//        String data = "";
//        this.allowComm();
//
//        
//        
//        //So now we need to download the login page first and collect up the cookies.  otherwise Wikipedia
//        //will think that we don't allow the setting of cookies.... Too bad. 
//
//
//        try {
//            loginURL = new URL("http", "localhost",8080,baseURL.toString()+ "index.php?title=Special:Userlogin");
//            loginConn = (HttpURLConnection) loginURL.openConnection();
//            grabCookiesLogin(loginConn, cookies);
//            InputStream is = loginURL.openStream();
//            BufferedReader br = new BufferedReader(new InputStreamReader(is)); //Should grab cookies for us.
//            while (br.ready()) {
//                data += br.readLine() + "\n";
//            }
//            
//            
//            br = new BufferedReader(new InputStreamReader(loginConn.getInputStream()));
//            String info = "";
//            //check out the response for any errors
//            while (br.ready()) {
//                info = info + br.readLine() + "\n";
//            }
//
//        } catch (Exception e) {
//            System.out.println("Failed Login.");
//            e.printStackTrace();
//        }
//
//        
//        try {
//            loginURL = new URL("http", "localhost",8080,baseURL.toString() + "index.php?title=Special:Userlogin&action=submitlogin&type=login");
//            loginConn = (HttpURLConnection) loginURL.openConnection();
//            //loginConn = loginURL.openConnection();
//
//            //loginConn.setDoOutput(true);
//            loginConn.setRequestMethod("POST");
//            setCookiesLogin(loginConn, cookies);
//
//            String bNum = "";
//            for (int i = 0; i < 12; i++) {
//                bNum = bNum + myRand.nextInt(10);
//            }
//
//            String fieldBreak = "---------------------------" + bNum;
//            //Now we need to build up all the info we are sending...
//            String conDisp = "Content-Disposition: form-data; ";
//            String sendData = "";
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//            sendData = sendData + conDisp + "name=\"wpName\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + userName + webLineSep;
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//
//            sendData = sendData + conDisp + "name=\"wpPassword\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + password + webLineSep;
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//
//            sendData = sendData + conDisp + "name=\"wpRemember\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + "1" + webLineSep;
//            sendData = sendData + "--" + fieldBreak + webLineSep;
//
//            //Last entry
//            sendData = sendData + conDisp + "name=\"wpLoginattempt\"" + webLineSep;
//            sendData = sendData + webLineSep;
//            sendData = sendData + "Log in" + webLineSep;
//            sendData = sendData + webLineSep + "--" + fieldBreak + "--" + webLineSep;
//
//            //setup the communicator for output...
//            loginConn.setDoOutput(true);
//            loginConn.setDoInput(true);
//            loginConn.setUseCaches(false);
//            loginConn.setRequestProperty("Content-Length", String.valueOf(sendData.length()));
//            loginConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + fieldBreak);
//            loginConn.setRequestProperty("User-Agent", " Mozilla/4.0 (compatible)");
//
//            System.out.println("Posting Data...");
//
//
//            OutputStream out = loginConn.getOutputStream();
//
//            //PrintWriter outp = new PrintWriter(out);
//
//            out.write(sendData.getBytes("UTF-8"));
//            out.flush();
//            out.close();
//
//            grabCookiesLogin(loginConn, cookies);
//            loginConn.getContent(); //Should grab cookies for us.
//            BufferedReader br = new BufferedReader(new InputStreamReader(loginConn.getInputStream()));
//            String info = "";
//            //check out the response for any errors
//            while (br.ready()) {
//                info = info + br.readLine() + "\n";
//            }
//
//
//            this.updateWait(this.LOGIN_WAIT);
//
//        } catch (Exception e) {
//            System.out.println("Failed Login.");
//            e.printStackTrace();
//        }
//        this.updateWait(this.LOGIN_WAIT);
    
    }    
    
    
    // something to handle cookies
    
    private HashMap cookies = new HashMap(12);
    private List<Cookie> cookieList = null;
    private void setCookiesLogin(URLConnection u, Map map) {

        //only difference is that we don't check the number of pre-existing cookies..
        Iterator i = map.entrySet().iterator();
        StringBuilder cookie = new StringBuilder(100);
        while (i.hasNext()) {
            Map.Entry entry = (Map.Entry) i.next();
            cookie.append(entry.getKey());
            cookie.append("=");
            cookie.append(entry.getValue());
            cookie.append("; ");
        }
        u.setRequestProperty("Cookie", cookie.toString());

    // enable gzip compression
    //u.setRequestProperty("Accept-encoding", "gzip");
    }

    private void setCookies(URLConnection u) {

        this.checkCookies();
        String cookieString = "";
        for (int i = 0; i < cookieList.size(); i++) {
            cookieString += cookieList.get(i).getName();
            cookieString += "=";
            cookieString += cookieList.get(i).getValue();
            cookieString += "; ";
        }
//        Iterator i = map.entrySet().iterator();
//        StringBuilder cookie = new StringBuilder(100);
//        
//        while (i.hasNext()) {
//            Map.Entry entry = (Map.Entry) i.next();
//            cookie.append(entry.getKey());
//            cookie.append("=");
//            cookie.append(entry.getValue());
//            cookie.append("; ");
//        }
        u.setRequestProperty("Cookie", cookieString);

    }
    
//    private void setCookies(URLConnection u, Map map) {
//
//
//        Iterator i = map.entrySet().iterator();
//        StringBuilder cookie = new StringBuilder(100);
//        this.checkCookies();
//        while (i.hasNext()) {
//            Map.Entry entry = (Map.Entry) i.next();
//            cookie.append(entry.getKey());
//            cookie.append("=");
//            cookie.append(entry.getValue());
//            cookie.append("; ");
//        }
//        u.setRequestProperty("Cookie", cookie.toString());
//
//    // enable gzip compression
//    //u.setRequestProperty("Accept-encoding", "gzip");
//    }

    
    
    private void grabCookiesLogin(URLConnection u, Map map) {
        // reset the cookie store
        //Don't really want to reset here - we will just overwrite cookies instead.
        //map.clear();
        String headerName = null;
        for (int i = 1; (headerName = u.getHeaderFieldKey(i)) != null; i++) {
            if (headerName.equals("Set-Cookie")) {
                String cookie = u.getHeaderField(i);

                // _session cookie is for cookies2, otherwise this causes problems
                //if (cookie.indexOf("_session") != -1 && map == cookies)
                //    continue;

                cookie = cookie.substring(0, cookie.indexOf(";"));
                String name = cookie.substring(0, cookie.indexOf("="));
                String value = cookie.substring(cookie.indexOf("=") + 1, cookie.length());
                map.put(name, value);
            }
        }
    }
    
    
    private void grabCookies(List<Cookie> list) {
        cookieList = list;
        if (cookieList == null) {
            System.out.println("!!!Warning!!! - No cookies recieved from login!!!");
        }
        else {
            if (cookieList.size() < 2) {
                System.out.println("!!!Warning!!! - Cookie list may be too small after login!!!");
            }
            
        }
    }
        
    private void checkCookies() {
        //This will get the necessary cookie data possibly logging back in.
                
        Date now = new Date();
        boolean reLogin = false;
        
        if (cookieList == null) {
            this.wikiLogin();
        }
        else {
            for(int i =0; i < cookieList.size(); i++) {
                if (cookieList.get(i).isExpired(now)) {
                    reLogin = true;
                }
            }
        }
        
        if (reLogin) {
            this.wikiLogin();
        }
                
        return;

    }

    /** Userful method to grab cookie data from the existing cookies and put it in a nice string
     * formatted for setrequest mothods.  Also logs the user in if the cookies have expired
     * or are missing.
     */
    private String getCookieData() {
        //This will get the necessary cookie data possibly logging back in.
        String data = "";
        List<HttpCookie> cookies;
        cookies = cStore.getCookies();

        //First make sure none have expired...
        boolean reLogin = false;
        if (cookies.size() < 4) {
            reLogin = true;
        }
        for (int i = 0; i < cookies.size(); i++) {
            HttpCookie cookie = cookies.get(i);
            if (cookie.hasExpired() == true) {
                reLogin = true;
            }
        }

        if (reLogin) {
            this.wikiLogin();
        }

        //String wikiToken ="";
        //String wikiUserName = "";
        //String wikiUserID ="";
        //String wiki_session = "";
        //System.out.println("Cookies toString: " + cookies.toString()); //DEBUG
        for (int i = 0; i < cookies.size(); i++) {
            HttpCookie cookie = cookies.get(i);

            if (i == 0) {
                data = encode(cookie.getName().trim()) + "=" + encode(cookie.getValue());
            } else {
                data = data + ", " + encode(cookie.getName().trim()) + "=" + encode(cookie.getValue());
            }
        }
        //Begin Debug
        //System.out.println("Cookie Data: " + data); //DEBUG
        //End Debug
        return data;
    }

    public String downloadPage(String page) throws Exception {
        //wraps for error catching.
        boolean clear = false;
        int tries = 0;
        while (!clear) {

            try {
                String data = downloadPageH(page);
                return data;
            } catch (Exception e) {
                System.out.println("Encountered Error while Downloading:");
                System.out.println(e.getMessage());
                if (tries < 3) {
                    System.out.println("Trying " + (3 - tries) + " more time(s) in 10 seconds...");
                    this.updateWait(10000);
                    this.allowComm();
                    tries++;


                } else {
                    System.out.println("3 tries failed; Requiring User Input:");
                    tries = 0;

                    try {
                        BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                        System.out.println("Try Again? (y/n)");
                        System.out.flush();
                        String input = inputLine.readLine();
                        //input = "y";
                        if (input.compareToIgnoreCase("y") == 0) {
                            clear = false;
                        } else {
                            clear = true;
                            throw new Exception("User Aborted Download due to error.", e);

                        }

                    } catch (IOException ex) {
                        throw new Exception("Unrecoverable IO Error.", ex);
                    //System.out.println("Unrecoverable IO Error.");
                    //ex.printStackTrace();
                    //System.exit(1);
                    }
                }
            }

        }
        throw new Exception("Unknown Download Error.");
    //return null;
    }

    /** Method to retrieve the code content of a wiki page.  returns null if the page
     * has no textbox (ie we are not allowed to create that page
     * returns and empty string if no code content existed for the page, or the page
     * did not yet exist, but we were allowed to create it.
     */
    private String downloadPageH(String page) throws Exception {
        //Returns the data of the indicated page. It is found in the wpTextbox1 area.
        String lineSep = System.getProperty("line.separator");
        page = encode(page);
        URL editURL;
        HttpURLConnection editConn;
        String data = "";

        //So max lag check is to speed up reading of the wiki pages, unless they are bogged down.
        //we will get a response of a single line if the server lags - we then need to wait for some amount
        //of time and repoll the server.
        editURL = new URL(baseURL, "index.php?title=" + page + "&action=edit&maxlag=" + this.MAX_LAG);
        //log.addEntry("SYSTEM","WIKICOMM","Downloading Page:"+ editURL.toString(),PBBLogging.logs.SY);

        MAX_LAG_CHECK:
        {
            boolean maxLagError = true;
            while (maxLagError) { //so go at least once.
                String fullData = "";
                this.allowComm();

                editConn = (HttpURLConnection) editURL.openConnection();
                setCookies(editConn);
                //editConn.setRequestProperty("Cookie", this.getCookieData());
                try {

                    editConn.getContent();
                } catch (IOException ex) {

                    if (editConn.getResponseCode() == HttpURLConnection.HTTP_UNAVAILABLE) {
                        BufferedReader br;

                        br = new BufferedReader(new InputStreamReader(editConn.getErrorStream()));

                        String line;

                        int readCount = 0;
                        fullData = "";
                        while ((line = br.readLine()) != null) {
                            fullData = fullData + line + lineSep;
                            readCount++;
                        }
                        if (readCount < 3) { //only read one or two lines - something was wrong.
                            if (fullData.matches("Waiting for .*: .* seconds lagged\\s*")) {
                                //looks like we were lagged
                                System.out.println("Server Lagged on Read. " + fullData);
                                String[] words = fullData.split("\\s+");
                                int waitTime = 0;
                                if (words.length > 3) {
                                    try {
                                        waitTime = Integer.parseInt(words[3]) * 1000;
                                    } catch (NumberFormatException nfe) {
                                        waitTime = 0;
                                    }
                                }

                                if (waitTime < this.READ_WAIT) {
                                    waitTime = this.READ_WAIT;
                                }

                                this.updateWait(waitTime);
                                continue;
                            } else {
                                throw ex;
                            }
                        } else {
                            throw ex;
                        }
                    } else {
                        throw ex;
                    }
                }

                //if we get here, no lag occured.
                InputStream is = editConn.getInputStream();
                int numRead;
                byte[] input = new byte[1024];
                //String fullData = "";
                //ArrayList fullData = new ArrayList();
                byte[] byteData = new byte[0];
                byte[] tmp = null;
                while ((numRead = is.read(input)) != -1) {
                    tmp = byteData;
                    byteData = new byte[tmp.length + numRead];
                    System.arraycopy(tmp, 0, byteData, 0, tmp.length);
                    System.arraycopy(input, 0, byteData, tmp.length, numRead);
                }

//                BufferedReader br = new BufferedReader(new InputStreamReader(is));
//                String line;
//                fullData = "";
//
//                while ( (line = br.readLine()) != null) {
//                    fullData = fullData + line + lineSep;
//                }
//
                fullData = new String(byteData, "UTF-8");
                //System.err.println(fullData);
                //byte[] theData;
                //theData = fullData.getBytes("UTF-16");

                data = this.parseTextArea(fullData);
                //Now clean up this data to remove HTML escape sequences.
                data = StringEscapeUtils.unescapeHtml(data);
                maxLagError = false;
            }


        } //END MAX_LAG_CHECK

        if (data == null) {
            data = "";
        }
        return data;


    }

    private String parseTextArea(String fullData) {
        //Helper function to extract the page data from the textarea entry.
        String data = "";
        int index1 = fullData.indexOf("name=\"wpTextbox1\"");
        if (index1 == -1) {
            //have no match, likely the page does not exist and we are not allowed to create it.
            data = null;
            return data;
        }
        int index2 = fullData.indexOf(">", index1);
        index1 = fullData.indexOf("</textarea>", index2);
        data = fullData.substring(index2 + 1, index1);
        if (data.trim().compareTo("") == 0) {
            //blank page or empty textbox.
            data = "";

        }
        return data;
    }

    public String getFullURL(String title) {
        URL editURL;
        String page = "";
        try {
            editURL = new URL(baseURL, "index.php?title=" + title);
            page = editURL.toString();
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
        return page;
    }

    public Hashtable<String, String> getPageDirectory(String page) throws Exception {
        //returns the name/page values for alternative location proteins.
        //They are stored in Name/Location pairs separated by a comma enclosed in '<>'
        Hashtable<String, String> data = new Hashtable<String, String>();
        String raw = downloadPage(page);
        if (raw == null) {
            return data;
        }
        raw = raw.trim();


        int index1 = 0;
        int index2 = 0;
        int commaIndex;
        String val1 = "";
        String val2 = "";
        if (raw.compareTo("") != 0) {
            while ((index1 = raw.indexOf("<", index2)) != -1) {

                if ((index2 = raw.indexOf(">", index1)) == -1) {
                    //we just set index2, it is possible that the pairs are open, so we'll call
                    //that an error and break here.
                    System.out.println("Error: bad format of Page Directory");
                    //log.addEntry("System","Error","Bad Format of Page Directory",PBBLogging.logs.ER);
                    break;
                }
                commaIndex = raw.indexOf(",", index1);
                if (commaIndex > index2 || commaIndex == -1) {
                    //No comma separation within that pair.
                    System.out.println("Error: bad format of Page Directory");
                    //log.addEntry("System","Error","Bad Format of Page Directory",PBBLogging.logs.ER);
                    break;
                }

                //Actually have some values here.
                val1 = raw.substring(index1 + 1, commaIndex).trim();
                val2 = raw.substring(commaIndex + 1, index2).trim();
                data.put(val1, val2);

            }
        } else {
            //log.addEntry("System","Warning","Page Directory has no data.",PBBLogging.logs.ER);
        }

        return data;

    }
    //Functions just like upload page, except that it appends information to the existing page.
    public void uploadAppendPage(String page, String text, String editComment) throws Exception {
        try {
            String data = this.downloadPage(page);
            data = data + text;
            this.uploadPage(page, data, editComment);
        } catch (Exception ex) {
            throw new Exception("Error While Appending.", ex);
        }
    }

    public void uploadPage(String page, String text, String editComment) throws Exception {
        //wraps for error catching.
        boolean clear = false;
        int tries = 0;
        while (!clear) {
            try {
                if (PbbUpdater.debugUpload == true) {
                    this.uploadPageH(page, text, editComment);
                } else {
                    System.out.println("Upload skipped due to Debug Upload being false.");
                }

                return;
            } catch (Exception e) {
                System.out.println("Encountered Error while Uploading:");
                System.out.println(e.getMessage());
                if (tries < 3) {
                    System.out.println("Trying " + (3 - tries) + " more time(s) in 10 seconds...");
                    this.updateWait(10000);
                    this.allowComm();
                    tries++;


                } else {
                    System.out.println("3 tries failed; Requiring User Input:");
                    tries = 0;

                    try {
                        BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                        System.out.println("Try Again? (y/n)");
                        System.out.flush();
                        String input = inputLine.readLine();
                        //input = "y";
                        if (input.compareToIgnoreCase("y") == 0) {
                            clear = false;
                        } else {
                            clear = true;
                            throw new Exception("User Aborted Upload due to error.", e);

                        }

                    } catch (IOException ex) {
                        throw new Exception("Unrecoverable IO Error.", ex);

                    }
                }
            }
        }
        throw new Exception("Upload Aborted.");

    }

    /** Method to upload a page to the wiki server.  Should log the user in first if
     * the user is not already logged in.
     * text is the page text,
     * page is the Title of the page to be editted.
     * editComment is the summary comment for the page edit.
     */
    public void uploadPageH(String page, String text, String editComment) throws Exception {
        //Upload a page to wikipedia.
        URL editURL;
        URLConnection editConn;
        URL postURL;
        HttpURLConnection postConn;
        String lineSep = System.getProperty("line.separator");
        String webLineSep = "\r\n";

        this.allowComm();

        //First do a little url encoding...

        page = encode(page);
        //editComment = encode(editComment);
        //Make sure the cookies are up to date
        //this.getCookieData();

        //Now open up the edit page so we can get data from it...
        editURL = new URL(baseURL, "index.php?title=" + page + "&action=edit");
        editConn = editURL.openConnection();
        setCookies(editConn);
        //editConn.setRequestProperty("Cookie", this.getCookieData());
        editConn.getContent();

        //get our hidden form values...
        Hashtable<String, String> hiddenVals = htmlParse(editConn.getInputStream());

        postURL = new URL(baseURL, "index.php?title=" + page + "&action=submit");
        postConn = (HttpURLConnection) postURL.openConnection();
        postConn.setRequestMethod("POST");
        setCookies(postConn);
        //postConn.setRequestProperty("Cookie", this.getCookieData());

        //postConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

//        log.addEntry("SYSTEM","WIKICOMM","Posting Data to:"+ postURL.toString(),PBBLogging.logs.SY);
//
//        System.out.println("Posting Data...");
//        //PrintWriter out = new PrintWriter(postConn.getOutputStream());
////        out.print("wpTextbox1=");
////        out.print(text);
////        out.print("&wpSummary=");
////        out.print(editComment);
////
//        for (int i=0; i<hiddenVals.size();i++){
//            if (hiddenVals.get(i).indexOf("wpSave") != -1 ) {
//                out.print("&wpSave=1");
//                continue;
//            }
//            if (hiddenVals.get(i).indexOf("wpDiff") != -1 )
//                continue;
//            if (hiddenVals.get(i).indexOf("wpPreview") != -1 )
//                continue;
//            out.print("&"+ hiddenVals.get(i));
//            //System.out.println("&"+ hiddenVals.get(i));
//        }
//        out.flush();
//        out.close();
//

        //******************

        String bNum = "";
        for (int i = 0; i < 12; i++) {
            bNum = bNum + myRand.nextInt(10);
        }

        String fieldBreak = "---------------------------" + bNum;
        //Now we need to build up all the info we are sending...
        String conDisp = "Content-Disposition: form-data; ";
        String sendData = "";
        sendData = sendData + "--" + fieldBreak + webLineSep;
        sendData = sendData + conDisp + "name=\"wpTextbox1\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + text + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpSummary\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + editComment + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpSave\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "1" + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpStarttime\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + hiddenVals.get("wpStarttime") + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpEdittime\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + hiddenVals.get("wpEdittime") + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpEditToken\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + hiddenVals.get("wpEditToken") + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        sendData = sendData + conDisp + "name=\"wpAutoSummary\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + hiddenVals.get("wpAutoSummary") + webLineSep;
        sendData = sendData + "--" + fieldBreak + webLineSep;

        //sendData = sendData + conDisp + "name=\"wpMinoredit\"" + webLineSep;
        //sendData = sendData + webLineSep;
        //sendData = sendData + "1" + webLineSep;
        //sendData = sendData + "--" + fieldBreak + webLineSep;

        //Last entry
        sendData = sendData + conDisp + "name=\"wpWatchthis\"" + webLineSep;
        sendData = sendData + webLineSep;
        sendData = sendData + "0" + webLineSep;
        sendData = sendData + webLineSep + "--" + fieldBreak + "--" + webLineSep;

        //setup the communicator for output...
        postConn.setDoOutput(true);
        postConn.setDoInput(true);
        postConn.setUseCaches(false);
        postConn.setRequestProperty("Content-Length", String.valueOf(sendData.length()));
        postConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + fieldBreak);

        //log.addEntry("SYSTEM","WIKICOMM","Posting Data to:"+ postURL.toString(),PBBLogging.logs.SY);

        System.out.println("Posting Data...");

        //DEBUG
        //System.err.println(sendData);

        OutputStream out = postConn.getOutputStream();

        //PrintWriter outp = new PrintWriter(out);

        out.write(sendData.getBytes("UTF-8"));
        out.flush();
        out.close();

        //outp.print(sendData);
        //outp.flush();
        //outp.close();

        //log.addEntry("SYSTEM","WIKICOMM","Finished Posting Data.",PBBLogging.logs.SY);

        System.out.println("Finished posting data.");

        //***************************

        //BEGIN DEBUG
        //System.out.println("Request Properties: " + postConn.getRequestProperties().toString());
        //END DEBUG
        //PrintWriter out = new PrintWriter(postConn.getOutputStream());
        //out.print("wpTextbox1=");
        //out.print(text);
        //out.print("&wpSummary=");
        //out.print(editComment);

//        for (int i=0; i<hiddenVals.size();i++){
//            if (hiddenVals.get(i).indexOf("wpSave") != -1 ) {
//                out.print("&wpSave=1");
//                continue;
//            }
//            if (hiddenVals.get(i).indexOf("wpDiff") != -1 )
//                continue;
//            if (hiddenVals.get(i).indexOf("wpPreview") != -1 )
//                continue;
//            out.print("&"+ hiddenVals.get(i));
//            //System.out.println("&"+ hiddenVals.get(i));
//        }
//        out.flush();
//        out.close();
//        //BEGIN DEBUG
//            /*String headerName;
//            for (int i = 1; (headerName = postConn.getHeaderFieldKey(i)) != null; i++){
//                System.out.println("Header - " + headerName + " - " + postConn.getHeaderField(i));
//
//            }*/
//        //END DEBUG


        //Now we need to read back the page..

        BufferedReader br = new BufferedReader(new InputStreamReader(postConn.getInputStream()));
        String info = "";
        //check out the response for any errors
        while (br.ready()) {
            info = info + br.readLine() + lineSep;
        }

        if (info.indexOf("Sorry! We could not process your edit due to a loss of session data.") != -1) {
            //log.addEntry("SYSTEM","WIKICOMM","Update Failed.  Loss of Session Data.",PBBLogging.logs.SY);

            System.out.println("Update failed. Loss of session data.");
        }

        postConn.getContent();

        this.updateWait(this.WRITE_WAIT);
        //Looks good.
        return;

    }

    /* used to parse specific data from an html page.  HtmlDataMine is a tight knit partner
     */
    private Hashtable<String, String> htmlParse(InputStream inPage) {
        Hashtable<String, String> data = null;
        System.out.println("Starting Web parse.");
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        Document importPage;
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            importPage = builder.parse(inPage);
            //System.out.println("Retrieving Data...");
            data = this.htmlDataMine(importPage);


        } catch (Exception e) {
            e.printStackTrace();
        }

        return data;

    }

    private Hashtable<String, String> htmlDataMine(Document doc) throws Exception {
        Hashtable<String, String> vals = null;

        Element root = doc.getDocumentElement();
        NodeList inputList = root.getElementsByTagName("input");

        vals = new Hashtable<String, String>();

        for (int i = 0; i < inputList.getLength(); i++) {
            Element tmpElement = (Element) inputList.item(i);

            //System.out.println("Input #" + i +": " + tmpElement.getAttribute("name") + " = " + tmpElement.getAttribute("value"));
            if ("hidden".compareToIgnoreCase(tmpElement.getAttribute("type")) == 0) {
                if ("".compareToIgnoreCase(tmpElement.getAttribute("value").trim()) != 0) {
                    vals.put(tmpElement.getAttribute("name"), tmpElement.getAttribute("value"));
                }
            }

        }

        return vals;
    }

    public static String encode(String in) {
        //Quick shortcut
        try {
            return URLEncoder.encode(in, "UTF-8");
        } catch (Exception e) {
            System.out.println("Error While Encoding.");
            return in;
        }
    }
}



